/*
 * $Id: rex.c,v 1.4 2005-12-20 15:26:56 bacon Exp $
 */

#include <xp/bas/rex.h>
#include <xp/bas/memory.h>
#include <xp/bas/string.h>

/* opcodes */
enum
{
	CHAR = 0x01,
	CHARSET,
	CHARSET_NOT,
	GROUP,
	BEGIN,
	END
};

/* character types */
enum {
	LBRACKET = 0x0000FF,
	RBRACKET,
	LBRACE,
	RBRACE,
	LPAREN,
	RPAREN,
	VBAR,
	CARET,
	DOLLAR,
	PLUS,
	QMARK,
	STAR,
	PERIOD,
	HYPHEN,
	COMMA
};

xp_rex_t* xp_rex_open (xp_rex_t* rex)
{
	if (rex == XP_NULL) {
		rex = (xp_rex_t*) xp_malloc (xp_sizeof(xp_rex_t));
		if (rex == XP_NULL) return XP_NULL;
		rex->__dynamic = xp_true;
	}
	else rex->__dynamic = xp_false;

	return rex;
}

void xp_rex_close (xp_rex_t* rex)
{
	if (rex->__dynamic) xp_free (rex);
}

int xp_rex_match (xp_rex_t* rex, const xp_char_t* str)
{
	return xp_rex_matchx (rex, str, xp_strlen(str));
}

int xp_rex_matchx (xp_rex_t* rex, const xp_char_t* str, xp_size_t len)
{
	return -1;
}

static int __compile (xp_rex_t* rex, const xp_char_t* ptn, xp_size_t len, int opt)
{
	const xp_char_t* p = ptn;
	const xp_char_t* end = ptn + len;

	if (len == 0) {
		/* it should always match */
		return 0;
	}

	/* TODO: do something ...
	if (opt & XP_REX_CASEFOLD) {
	}
	*/

	/* inspect the pattern */
	while (p < end) {
		if (*p == XP_CHAR('[')) {
		}
		else if (*p == XP_CHAR(']')) {
		}
		else if (*p == XP_CHAR('\\')) {
		}
		else if (*p == XP_CHAR('(')) {
		}
		else if (*p == XP_CHAR(')')) {
		}
		else if (*p == XP_CHAR('.')) {
		}
		else if (*p == XP_CHAR('{')) {
		}
		else if (*p == XP_CHAR('}')) {
		}
		else if (*p == XP_CHAR('*') || *p == XP_CHAR('?')) {
		}
		else if (*p == XP_CHAR('|') || *p == XP_CHAR('+')) {
		}
		else {
		} 
	}

	return 0;
}

static xp_cint_t __getchar_top (xp_char_t c)
{
	return 
		(c == '[')? LBRACKET:
		(c == '|')? VBAR:
		(c == '^')? CARET:
		(c == '$')? DOLLAR:
		(c == '{')? LBRACE:
		(c == '+')? PLUS:
		(c == '?')? QMARK:
		(c == '*')? STAR:
		(c == '.')? PERIOD:
		(c == '(')? LPAREN:
		(c == ')')? RPAREN: c;
	
}

static xp_cint_t __getchar_charset (xp_char_t c)
{
	return 
		(c == '^')? CARET:
		(c == '-')? HYPHEN:
		(c == ']')? RBRACKET: c;
}

static xp_cint_t __getchar_bound (xp_char_t c)
{
	return 
		(c == ',')? COMMA:
		(c == ']')? RBRACE: c;
}

static xp_cint_t __getchar (int level, xp_char_t c)
{
	typedef xp_cint_t (*func_type) (xp_char_t);
	static func_type __getchar_level[] =
	{
		__getchar_top,
		__getchar_charset,
		__getchar_bound
	};	

	return __getchar_level[level] (c);
}
